package ch.ethz.fcl.metrobuzz.data.interchange;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.vecmath.Vector2d;

import ch.ethz.fcl.metrobuzz.MBProperty;
import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.data.scene.basemap.Edge;
import ch.ethz.fcl.metrobuzz.render.techniques.circos.CircosDiagram;
import ch.ethz.fcl.metrobuzz.render.techniques.circos.CircosMatrix;
import ch.ethz.fcl.metrobuzz.render.techniques.circos.version5.CircosDiagram5;
import ch.ethz.fcl.metrobuzz.render.techniques.colors.MBColorTable;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Rectangle;
import ch.ethz.fcl.metrobuzz.tools.MBTools;
import ch.ethz.fcl.metrofont.MetroFont;

public class Interchange {
	protected int index;
	protected int colorIndex = -1;

	protected Point2D circosCentroid;

	protected List<Edge> edges;
	protected List<Edge> incomingEdges;
	protected List<Edge> outgoingEdges;

	protected List<Integer>[] outgoingTripIds;
	protected List<Integer>[] incomingTripIds;

	// records the connected interchanges and their indices
	protected List<Interchange> connectedInterchanges;
	protected List<Integer> connectedInterchangeIndices;
	protected List<Integer> connectedInterchangeColorIndices;

	// arc elements corresponding connected interchange and its color
	protected Map<Interchange, Integer> arcElementColorMap;

	protected Vector2d[] linkDirs;
	protected int[] linkColors;
	protected float circosRadius = 0.01f;
	protected int matrixSize = 0; // exterior links size

	protected CircosDiagram cd = null;

	// record the distribution such that segments of traffic data can be added
	protected int[][][] totalDistribution;
	protected int[][][] distribution;

	protected String folderName = MBProperty.INTERCHANGE_FOLDER;

	public void initCircos() {
		CircosMatrix cm = getData(MBData.startTime, MBData.startTime
				+ MBData.period);
		cd = new CircosDiagram5(getCircosCentroid(), circosRadius, cm);
	}

	public void setCircosDiagram(CircosDiagram cd) {
		this.cd = cd;
		this.circosCentroid = cd.getCentroid();
	}

	public void setColorIndex(int index) {
		this.colorIndex = index;
	}

	public void setCentroid(float x, float y) {
		if (circosCentroid == null)
			circosCentroid = new Point2D(x, y);
		circosCentroid.setX(x);
		circosCentroid.setY(y);

		if (cd != null)
			cd.updateCenter(circosCentroid);
	}

	public void setRadius(float radius) {
		circosRadius = radius;
		if (cd != null)
			cd.updateRadius(circosRadius);
	}

	protected void setColorMap(Region r, int color) {
		if (!arcElementColorMap.containsKey(r))
			arcElementColorMap.put(r, color);
	}

	public void addConnectedInterchange(Interchange interchange) {
		if (connectedInterchanges == null)
			connectedInterchanges = new ArrayList<Interchange>();
		connectedInterchanges.add(interchange);
	}

	public void addConnectedInterchangeIndex(int index) {
		if (connectedInterchangeIndices == null)
			connectedInterchangeIndices = new ArrayList<Integer>();
		connectedInterchangeIndices.add(index);
	}

	public void addConnectedInterchangeColor(int index, int color) {
		if (connectedInterchangeColorIndices == null)
			connectedInterchangeColorIndices = new ArrayList<Integer>();
		connectedInterchangeColorIndices.add(index, color);
	}

	public int getIndex() {
		return index;
	}

	public int getColorIndex() {
		return colorIndex;
	}

	public CircosDiagram getCircos() {
		return cd;
	}

	protected List<Integer> getArcElementColors() {
		List<Integer> colors = new ArrayList<Integer>();
		if (arcElementColorMap == null)
			return colors;

		for (Interchange interchange : arcElementColorMap.keySet()) {
			Integer c = arcElementColorMap.get(interchange);
			if (c != null)
				colors.add(c);
		}
		return colors;
	}

	public CircosMatrix getData(int startIndex, int endIndex) {
		CircosMatrix cd = new CircosMatrix(matrixSize);
		if (startIndex < 95 && endIndex > 0)
			for (int i = 0; i < matrixSize; i++) {
				for (int j = 0; j < matrixSize; j++) {
					int[] dis = Arrays.copyOfRange(distribution[i][j],
							Math.max(0, startIndex), Math.min(95, endIndex));
					int sum = MBTools.sum(dis);

					cd.setData(i, j, sum);
				}
				if (i > 0) {
					cd.getDirections().setDirection(i, linkDirs[i - 1]);
					cd.setColor(i, linkColors[i - 1]);
				}
			}
		cd.setColor(0, MBColorTable.LIGHTGREY);
		return cd;
	}

	public float getCircosRadius() {
		return circosRadius;
	}

	public Point2D getCircosCentroid() {
		return circosCentroid;
	}

	public List<Interchange> getConnectedInterchanges() {
		return connectedInterchanges;
	}

	public void render(Rectangle bound, MetroFont fm) {
	}
}
